//	--------------------------------------------------------------------
//	Copyright(C) 2006,2007 Zhao Yukun. All rights reserved.
//	This file is a part of the Xeres system.
//	Xeres 2007
//	Contact : xeres.engine@gmail.com
//	$(reservedInfo)
//	$(reservedDeclaration)
//	--------------------------------------------------------------------
///	@file	<CBlendState9.cpp>
///	@path	~/src/graphics/dx9/
///	@date	2008/12/22
///	@desc	.

#include "config/config.h"

#include "graphics/RenderContext.h"
#include "graphics/dx9/CBlendState9.h"

namespace xeres {

	IMPL_IOBJECT_CLASS( CBlendState9 );

	namespace
	{
		static inline DWORD to_op( BlendOpType op )
		{
			switch( op )
			{
			case BLENDOP_ADD: return D3DBLENDOP_ADD;
			case BLENDOP_SUB: return D3DBLENDOP_SUBTRACT;
			case BLENDOP_RSUB: return D3DBLENDOP_REVSUBTRACT;
			case BLENDOP_MIN: return D3DBLENDOP_MIN;
			case BLENDOP_MAX: return D3DBLENDOP_MAX;
			}
			XS_ASSERT(false);
			return 0;
		}

		static inline DWORD to_type( BlendType type )
		{
			switch( type )
			{
			case BLEND_ZERO: return D3DBLEND_ZERO;
			case BLEND_ONE: return D3DBLEND_ONE;
			case BLEND_SRCCOLOR: return D3DBLEND_SRCCOLOR;
			case BLEND_INVSRCCOLOR: return D3DBLEND_INVSRCCOLOR;
			case BLEND_SRCALPHA: return D3DBLEND_SRCALPHA;
			case BLEND_INVSRCALPHA: return D3DBLEND_INVSRCALPHA;
			case BLEND_DESTALPHA: return D3DBLEND_DESTALPHA;
			case BLEND_INVDESTALPHA: return D3DBLEND_INVDESTALPHA;
			case BLEND_DESTCOLOR: return D3DBLEND_DESTCOLOR;
			case BLEND_INVDESTCOLOR: return D3DBLEND_INVDESTCOLOR;
			case BLEND_SRCALPHASAT: return D3DBLEND_SRCALPHASAT;
			case BLEND_BLENDFACTOR: return D3DBLEND_BLENDFACTOR;
			case BLEND_INVBLENDFACTOR: return D3DBLEND_INVBLENDFACTOR;
			}
			XS_ASSERT(false);
			return 0;
		}
	}
	// CBlendState9
	CBlendState9::CBlendState9( BlendSet& blend_set )
	{
		m_states.push_back( std::make_pair( D3DRS_ALPHABLENDENABLE , blend_set.enable_blend[0] ? TRUE : FALSE ) );
		if( blend_set.enable_blend[0] )
		{
			DWORD color_op = to_op( blend_set.color_op );
			DWORD color_src = to_type( blend_set.color_src );
			DWORD color_dst = to_type( blend_set.color_dst );
			m_states.push_back( std::make_pair( D3DRS_BLENDOP , color_op ) );
			m_states.push_back( std::make_pair( D3DRS_SRCBLEND , color_src ) );
			m_states.push_back( std::make_pair( D3DRS_DESTBLEND , color_dst ) );

			m_states.push_back( std::make_pair( D3DRS_SEPARATEALPHABLENDENABLE , blend_set.separate_alpha ? TRUE : FALSE ) );
			if( blend_set.separate_alpha )
			{
				DWORD alpha_op = to_op( blend_set.alpha_op );
				DWORD alpha_src = to_type( blend_set.alpha_src );
				DWORD alpha_dst = to_type( blend_set.alpha_dst );
				m_states.push_back( std::make_pair( D3DRS_BLENDOPALPHA , alpha_op ) );
				m_states.push_back( std::make_pair( D3DRS_SRCBLENDALPHA , alpha_src ) );
				m_states.push_back( std::make_pair( D3DRS_DESTBLENDALPHA , alpha_dst ) );
			}
		}
		if( blend_set.color_write[0] > 0 )
		{
			DWORD write = 0;
			if( blend_set.color_write[0] & COLOR_WRITE_RED ) write |= D3DCOLORWRITEENABLE_RED;
			if( blend_set.color_write[0] & COLOR_WRITE_GREEN ) write |= D3DCOLORWRITEENABLE_GREEN;
			if( blend_set.color_write[0] & COLOR_WRITE_BLUE ) write |= D3DCOLORWRITEENABLE_BLUE;
			if( blend_set.color_write[0] & COLOR_WRITE_ALPHA ) write |= D3DCOLORWRITEENABLE_ALPHA;
			m_states.push_back( std::make_pair( D3DRS_COLORWRITEENABLE , write ) );
		}
	}
	// ~CBlendState9
	CBlendState9::~CBlendState9( void )
	{
	}
	// Apply
	void CBlendState9::Apply( RenderContext& rc )
	{
		IDirect3DDevice9 * d9 = rc.GetDX9();
		for( size_t i = 0 ; i < m_states.size() ; ++i )
		{
			std::pair<D3DRENDERSTATETYPE,DWORD>& s = m_states[i];
			d9->SetRenderState( s.first , s.second );
		}
	}
} // namespace xeres
